package com.ssy.lingxi.marketing.serviceimpl;

import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.entity.activity.MerchantActivityDO;
import com.ssy.lingxi.marketing.entity.activity.PlatformActivityDO;
import com.ssy.lingxi.marketing.entity.coupon.MerchantCouponDO;
import com.ssy.lingxi.marketing.entity.coupon.PlatformCouponDO;
import com.ssy.lingxi.marketing.model.constant.MarketingConstants;
import com.ssy.lingxi.marketing.model.constant.TaskTypeEnum;
import com.ssy.lingxi.marketing.service.IScheduleFeignService;
import com.ssy.lingxi.scheduler.api.feign.ScheduleTaskFeign;
import com.ssy.lingxi.scheduler.api.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  feign内部接口实现
 * @author ds
 * @date 2021/7/23
 * @version 2.0.0
 */
@Slf4j
@Service
public class ScheduleFeignServiceImpl implements IScheduleFeignService {

    @Resource
    private ScheduleTaskFeign scheduleTaskFeign;
    /**
     * 延长定时执行30秒
     * t: 当前时间 a: 要执行的时间 a > t
     * 延长原因为, 当新增数据后所需要执行的时间为a, 当前时间为t1, 符合条件 a > t, 当t无限接近a的时候, 会出现情况当前时间t2 >= a
     * 因为代码也要时间, 服务之间调用也需要时间, 所以可能造成t > a的情况, 所以延长一分钟
     * 不延长也可以, 定时服务的参数校验去掉, 不然还是会出现新增定时任务失败的情况
     */
    private static long delayTime = 30 * 1000;

    @Override
    public Wrapper<List<ScheduleTaskDefinitionVO>> listScheduleTask(ScheduleTaskQueryVO queryVO) {
        queryVO.setServiceName(MarketingConstants.service_name);
        return scheduleTaskFeign.listScheduleTask(queryVO);
    }

    @Override
    public Wrapper<Void> updateScheduleTaskExecTime(ScheduleTaskUpdateExecTimeVO updateVO) {
        return scheduleTaskFeign.updateScheduleTaskExecTime(updateVO);
    }

    @Override
    public Wrapper<Long> addSchedulerTask(ScheduleTaskVO scheduleTaskVO) {
        log.info("addSchedulerTask:input param:{}", JSONUtil.toJsonStr(scheduleTaskVO));
        scheduleTaskVO.setServiceName(MarketingConstants.service_name);
        if (!StringUtils.hasLength(scheduleTaskVO.getCallbackUrl())) {
            scheduleTaskVO.setCallbackUrl(MarketingConstants.TASK_CALLBACK_URL);
        }
        Wrapper<Long> scheduleTask = scheduleTaskFeign.createScheduleTask(scheduleTaskVO);
        log.info("addSchedulerTask:out param:{}", JSONUtil.toJsonStr(scheduleTask));
        return scheduleTask;
    }

    @Override
    public Wrapper<Long> createPermanentTask(PermanentTaskVO scheduleTaskVO) {
        return scheduleTaskFeign.createPermanentTask(scheduleTaskVO);
    }

    @Override
    public void createSignUpStartTask(UserLoginCacheDTO loginUser, PlatformActivityDO platformActivityDO) {
        // 定时任务, [报名时间开始]触发状态变更为: 待报名 -> 待审核报名
        ScheduleTaskVO signUpStartTaskVO = new ScheduleTaskVO();
        signUpStartTaskVO.setMemberId(loginUser.getMemberId());
        signUpStartTaskVO.setRoleId(loginUser.getMemberRoleId());
        signUpStartTaskVO.setExecTime(platformActivityDO.getSignUpStartTime() + delayTime);
        signUpStartTaskVO.setDataIds(Collections.singletonList(platformActivityDO.getId()));
        Map<String, Object> signUpStartTaskAttributes = new HashMap<>();
        signUpStartTaskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.PF_ACTIVITY_SIGN_UP_START.getCode());
        signUpStartTaskAttributes.put(TaskTypeEnum.Constants.PLATFORM_USER, loginUser);
        signUpStartTaskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, platformActivityDO.getSignUpStartTime());
        signUpStartTaskVO.setTaskAttributes(signUpStartTaskAttributes);
        try {
            Wrapper<Long> signUpStartTaskWrapper = this.addSchedulerTask(signUpStartTaskVO);
            if (ResponseCode.SUCCESS.getCode() != signUpStartTaskWrapper.getCode()) {
                log.error("平台活动提交, 创建报名开始定时任务失败: {}", signUpStartTaskWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("平台活动提交, 创建报名开始定时任务失败", e);
        }
    }

    @Override
    public void createSignUpEndTask(UserLoginCacheDTO loginUser, PlatformActivityDO platformActivityDO) {
        // 定时任务, [报名时间结束]触发状态变更为: 待审核报名 -> 待上线活动
        ScheduleTaskVO signUpEndTaskVO = new ScheduleTaskVO();
        signUpEndTaskVO.setMemberId(loginUser.getMemberId());
        signUpEndTaskVO.setRoleId(loginUser.getMemberRoleId());
        signUpEndTaskVO.setExecTime(platformActivityDO.getSignUpEndTime() + delayTime);
        signUpEndTaskVO.setDataIds(Collections.singletonList(platformActivityDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.PF_ACTIVITY_SIGN_UP_END.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.PLATFORM_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, platformActivityDO.getSignUpEndTime());
        signUpEndTaskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> signUpEndTaskWrapper = this.addSchedulerTask(signUpEndTaskVO);
            if (ResponseCode.SUCCESS.getCode() != signUpEndTaskWrapper.getCode()) {
                log.error("平台活动提交, 创建报名结束定时任务失败: {}", signUpEndTaskWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("平台活动提交, 创建报名结束定时任务失败", e);
        }
    }

    @Override
    public void createPfActivityEndTask(UserLoginCacheDTO loginUser, PlatformActivityDO platformActivityDO) {
        // 活动结束定时任务
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(platformActivityDO.getEndTime() + delayTime);
        taskVO.setDataIds(Collections.singletonList(platformActivityDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.PF_ACTIVITY_END.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.PLATFORM_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, platformActivityDO.getEndTime());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("创建平台活动, 创建活动定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("创建平台活动, 创建活动定时任务失败", e);
        }
    }

    @Override
    public void createMcActivityEndTask(UserLoginCacheDTO loginUser, MerchantActivityDO merchantActivityDO) {
        // 活动结束定时任务
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(merchantActivityDO.getEndTime() + delayTime);
        taskVO.setDataIds(Collections.singletonList(merchantActivityDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.MC_ACTIVITY_END.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.ABILITY_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, merchantActivityDO.getEndTime());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("创建商家活动, 创建活动定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("创建商家活动, 创建活动定时任务失败", e);
        }
    }

    @Override
    public void createPfCouponReleaseStartTask(UserLoginCacheDTO loginUser, PlatformCouponDO platformCouponDO) {
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(platformCouponDO.getReleaseTimeStart() + delayTime);
        taskVO.setDataIds(Collections.singletonList(platformCouponDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.PF_COUPON_RELEASE_START.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.PLATFORM_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, platformCouponDO.getReleaseTimeStart());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("平台优惠券提交, 创建发放开始定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("平台优惠券提交, 创建发放开始定时任务失败", e);
        }
    }

    @Override
    public void createPfCouponReleaseEndTask(UserLoginCacheDTO loginUser, PlatformCouponDO platformCouponDO) {
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(platformCouponDO.getReleaseTimeEnd() + delayTime);
        taskVO.setDataIds(Collections.singletonList(platformCouponDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.PF_COUPON_RELEASE_END.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.PLATFORM_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, platformCouponDO.getReleaseTimeEnd());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("平台优惠券提交, 创建发放结束定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("平台优惠券提交, 创建发放结束定时任务失败", e);
        }
    }

    @Override
    public void createMcCouponReleaseStartTask(UserLoginCacheDTO loginUser, MerchantCouponDO merchantCouponDO) {
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(merchantCouponDO.getReleaseTimeStart() + delayTime);
        taskVO.setDataIds(Collections.singletonList(merchantCouponDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.MC_COUPON_RELEASE_START.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.ABILITY_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, merchantCouponDO.getReleaseTimeStart());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("商家优惠券提交, 创建发放开始定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("商家优惠券提交, 创建发放开始定时任务失败", e);
        }
    }

    @Override
    public void createMcCouponReleaseEndTask(UserLoginCacheDTO loginUser, MerchantCouponDO merchantCouponDO) {
        ScheduleTaskVO taskVO = new ScheduleTaskVO();
        taskVO.setMemberId(loginUser.getMemberId());
        taskVO.setRoleId(loginUser.getMemberRoleId());
        taskVO.setExecTime(merchantCouponDO.getReleaseTimeEnd() + delayTime);
        taskVO.setDataIds(Collections.singletonList(merchantCouponDO.getId()));
        Map<String, Object> taskAttributes = new HashMap<>();
        taskAttributes.put(TaskTypeEnum.Constants.NAME, TaskTypeEnum.MC_COUPON_RELEASE_END.getCode());
        taskAttributes.put(TaskTypeEnum.Constants.ABILITY_USER, loginUser);
        taskAttributes.put(TaskTypeEnum.Constants.EXECUTE_TIME, merchantCouponDO.getReleaseTimeEnd());
        taskVO.setTaskAttributes(taskAttributes);
        try {
            Wrapper<Long> scheduleWrapper = this.addSchedulerTask(taskVO);
            if (ResponseCode.SUCCESS.getCode() != scheduleWrapper.getCode()) {
                log.error("商家优惠券提交, 创建发放结束定时任务失败: {}", scheduleWrapper.getMessage());
            }
        } catch (Exception e) {
            log.error("商家优惠券提交, 创建发放结束定时任务失败", e);
        }
    }
}
